package com.smart.tool.excel;


import cn.idev.excel.context.AnalysisContext;
import cn.idev.excel.event.AnalysisEventListener;
import cn.idev.excel.exception.ExcelDataConvertException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

import com.smart.tool.core.ICallBack;

/**
 * @Author xiaoqiang
 * @Version ExcelEventListenerUtils.java, v 0.1 2024年07月10日 下午10:11 xiaoqiang
 * @Description: TODO 基于easyexcel实现的excel读取工具
 */
public class ExcelEventListenerUtils {
    private static final Logger logger = LoggerFactory.getLogger(ExcelEventListenerUtils.class);

    private ExcelEventListenerUtils() {

    }


    public static class ExcelAnalysisEventListener<T> extends AnalysisEventListener<T> {
        private List<ICallBack> iCallBacks = new ArrayList<>();
        private List<T> linkedList = new ArrayList<T>();
        private int num = 0;
        private boolean exceptionFlag = true;
        private int tick = 0;
        private Integer threshold = Integer.MAX_VALUE;
        private Consumer<List<T>> consumer = null;

        private List<Map<Integer, String>> headerMapList = new ArrayList<>();

        public ExcelAnalysisEventListener(Consumer<List<T>> consumer,  boolean exceptionFlag, int threshold) {
            this(consumer);
            this.exceptionFlag = exceptionFlag;
            this.threshold = threshold;
        }

        public ExcelAnalysisEventListener(Consumer<List<T>> consumer) {
            this.consumer = consumer;
        }

        public void addICallBack(ICallBack iCallBack) {
            iCallBacks.add(iCallBack);
        }

        public void remove(ICallBack iCallBack) {
            iCallBacks.remove(iCallBack);
        }

        public List<Map<Integer, String>> getHeaderMapList() {
            return headerMapList;
        }

        @Override
        public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
            num++;
            headerMapList.add(headMap);
        }

        @Override
        public void onException(Exception exception, AnalysisContext context) {
            if (exceptionFlag == false) {
                return;
            }

            if (exception instanceof ExcelDataConvertException) {
                int sheetNo = context.readSheetHolder().getSheetNo();
                ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException) exception;
                String errMsg = "第" + sheetNo + "页，第" + num
                        + "行，解析错误,列数据 " + excelDataConvertException.getCellData();
                logger.error(errMsg, exception);
                throw new RuntimeException(errMsg, exception);
            }
            linkedList.clear();
            logger.error(exception.getMessage(), exception);
            throw new RuntimeException(exception.getMessage(), exception);
        }

        @Override
        public void invoke(T t, AnalysisContext analysisContext) {
            Boolean flag = true;
            if (!iCallBacks.isEmpty()) {
                int sheetNo = analysisContext.readSheetHolder().getSheetNo();
                for (ICallBack iCallBack : iCallBacks) {
                    flag = (Boolean) iCallBack.callBack(t, num++, sheetNo, headerMapList, analysisContext);
                    if (flag == null || flag == false) {
                        break;
                    }
                }
            }
            if (flag == true) {
                linkedList.add(t);
            }
            if (linkedList.size() >= threshold) {
                consumer.accept(linkedList);
                if (linkedList != null) {
                    linkedList.clear();
                }
            }
        }




        @Override
        public void doAfterAllAnalysed(AnalysisContext analysisContext) {
            if (linkedList.size() > 0) {
                consumer.accept(linkedList);
                if (linkedList != null) {
                    linkedList.clear();
                }

                num = 0;
            }
        }
    }

    /**
     * @param consumer      批量处理逻辑
     * @param exceptionFlag 如果为false，直接返回不抛出异常
     * @param threshold     批量处理阈值 ，如果总数是6000，则
     * @param <T>
     * @return
     */
    public static <T> ExcelAnalysisEventListener<T> getListener(Consumer<List<T>> consumer,
                                                                Boolean exceptionFlag,
                                                                Integer threshold) {
        return new ExcelAnalysisEventListener<T>(consumer, exceptionFlag, threshold);
    }
}
